<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
 * PHP version 5
 *
 * This source file is subject to version 2.1 of the GNU Lesser General Public
 * License, that is bundled with this package in the file COPYING, available
 * through the world wide web at the following URI:
 * http://www.gnu.org/copyleft/lesser.html.
 *
 * @package    ZNF
 * @author     Alessandro Rossini <http://www.alessandrorossini.org>
 * @author     Graziano Liberati <http://www.liberati.org>
 * @author     Tomasz Kuter <evolic@interia.pl>
 * @copyright  2004-2007 The ZNF Development Team
 * @license    LGPL License 2.1 <http://www.gnu.org/copyleft/lesser.html>
 * @version    SVN $Id: ZNF.php 44 2007-07-22 23:55:30Z evolic $
 * @since      Release 0.6.1
 * @link       http://www.zeronotice.org
 */

require_once('ZNF/Action/RequestProcessor.php');
require_once('ZNF/Config/AppConfig.php');
require_once('ZNF/Config/ModulesConfig.php');
require_once('ZNF/Presentation/Translation.php');

/**
 * <i>ZNF</i> provides the controller in the Model-View-Controller (MVC) design pattern for web applications that is commonly known as Model 2.
 *
 * @access     public
 * @package    ZNF
 * @author     Alessandro Rossini <http://www.alessandrorossini.org>
 * @author     Graziano Liberati <http://www.liberati.org>
 * @author     Tomasz Kuter <evolic@interia.pl>
 * @copyright  2004-2007 The ZNF Development Team
 * @license    LGPL License 2.1 <http://www.gnu.org/copyleft/lesser.html>
 * @version    SVN $Id: ZNF.php 44 2007-07-22 23:55:30Z evolic $
 * @since      Release 0.6.1
 * @link       http://www.zeronotice.org
 */
class ZNF
{

    /**
     * Version of the framework.
     */
    const VERSION = '0.7.10';

    /**
     * Name of the GET attribute used to select the action to execute.
     */
    const ACTION_INDEX = 'znfAction';

    /**
     * Name of the GET attribute used to select the module configuration.
     */
    const MODULE_INDEX = 'znfModule';

    /**
     * Name of the GET attribute used to select persistently the module configuration.
     */
    const CHANGE_MODULE_INDEX = 'znfChangeModule';

    /**
     * Name of the cache directory.
     */
    const CACHE_DIR = 'cache';

    /**
     * Name of the config directory.
     */
    const CONFIG_DIR = 'config';

    /**
     * Name of the language directory.
     */
    const LANG_DIR = 'lang';

    /**
     * Name of the libraries directory.
     */
    const LIB_DIR = 'lib';

    /**
     * Name of the modules directory.
     */
    const MODULES_DIR = 'modules';

    /**
     * Name of the package templates directory.
     */
    const TEMPLATE_DIR = 'templates';

    /**
     * Name of the package templates overlay directory.
     */
    const TEMPLATE_OVERLAY_DIR = 'packages';

    /**
     * Name of the theme directory.
     */
    const THEME_DIR = 'themes';

    /**
     * Debugging mode, set to true if you want to debug the application.
     */
    const DEBUG = false;

    /**
     * ZNF credits, don't modify the line below.
     */
    const CREDITS = 'Powered by <a target="_blank" href="http://www.zeronotice.org">ZNF</a> &raquo; &copy; 2004-2007 The ZNF Development Team &raquo; Released under the <a target="_blank" href="http://www.gnu.org/copyleft/lesser.html">GNU/LGPL</a> license';

    /**
     * Constructs a new <i>ZNF</i> object.
     *
     * @access public
     */
    public function __construct()
    {
        set_include_path(get_include_path() . PATH_SEPARATOR . self::LIB_DIR . '/');
        $this->_startSession();
    }

    /**
     * Processes the action requested with the correct <i>ZNF_Action_RequestProcessor</i>.
     *
     * @access public
     * @return boolean
     */
    public function process()
    {
        $path = $this->_processPath();
        $module = $this->_processModule();

        $appConfig = ZNF_Config_AppConfig::getInstance();

        // get the app module config
        $appModuleConfig = $appConfig->findModule($module);

        // custom request processor selected
        if ($appModuleConfig['processor']) {
            $file = preg_replace('/_/', '/', $appModuleConfig['processor']) . '.php';

            // selected custom request processor not found
            if (!file_exists($file)) {
                $translation = new ZNF_Presentation_Translation('ZNF', $_SESSION['znf']['lang']);
                throw new ZNF_Action_RequestProcessorException($translation->get('errorLoadRequestProcessor'));
            }

            // requires the file of the of the custom request processor
            require_once($file);
            $processor = new $appModuleConfig['processor']($module);
        } else {
            $processor = new ZNF_Action_RequestProcessor($module);
        }

        $processor->preProcess($path);
        $processor->process($path);
        $processor->postProcess($path);

        return true;
    }

    /**
     * Starts or reloads the session, setting the proper framework attributes for language, locale, theme and sessionId.
     *
     * @access protected
     * @return boolean
     */
    protected function _startSession()
    {
        $appConfig = ZNF_Config_AppConfig::getInstance();

        // get defaults from the configuration file
        $sessionId = $appConfig->getSessionId();
        $sessionPrevId = session_name($sessionId);

        // starts a new session if new session name is not equal previous
        if ($sessionPrevId != $sessionId) {
            session_start();
        }
        // starts a new session if not set
        if (!isset($_SESSION['znf']['id'])) {
            $lang   = $appConfig->getLang();
            $locale = $appConfig->getLocale();
            $theme  = $appConfig->getTheme();

            if ($appConfig->getLangAutodetect() != 'false') {
                // get language from the browser
                if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
                    $browserLang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'],0,2);

                    if (file_exists(self::THEME_DIR . "/{$theme}/{$browserLang}")) {
                        $lang = $browserLang;
                    }

                }
            }

            // initializes session with framework attributes
            $_SESSION['znf']['id']            = session_id();
            $_SESSION['znf']['lang']          = $lang;
            $_SESSION['znf']['locale']        = $locale;
            $_SESSION['znf']['theme']         = $theme;
            $_SESSION['znf']['authenticated'] = false;
            $_SESSION['znf']['roles']         = array();
        }
        setlocale(LC_ALL, $_SESSION['znf']['locale']);

        return true;
    }

    /**
     * Extracts the name of the action from the request.
     *
     * This method returns <i>null</i> if no action is found, then the
     * <i>ZNF_Action_RequestProcessor->_processMapping()</i> select the default
     * <i>action</i> element from the module configuration file.
     *
     * @access protected
     * @return string
     */
    protected function _processPath()
    {
        if (array_key_exists(ZNF::ACTION_INDEX, $_GET)) {
            return $_GET[ZNF::ACTION_INDEX];
        }

        return null;
    }

    /**
     * Extracts the name of the module from the request.
     *
     * This method returns <i>null</i> if no module is found, then the
     * <i>ZNF_Config_ModulesConfig::getInstance()</i> returns the configuration
     * of the default <i>module</i> element from the application configuration
     * file.
     *
     * @access protected
     * @return string
     */
    protected function _processModule()
    {
        if (array_key_exists(ZNF::CHANGE_MODULE_INDEX, $_GET)) {
            $_SESSION['module'] = $_GET[ZNF::CHANGE_MODULE_INDEX];
        }

        if (array_key_exists(ZNF::MODULE_INDEX, $_GET)) {
            return $_GET[ZNF::MODULE_INDEX];
        }

        if (isset($_SESSION['module'])) {
            return $_SESSION['module'];
        }

        return null;
    }

    /**
     * Update the name of the action in the request.
     *
     * This method is used by the <i>ZNF_Action_RequestProcessor</i> to forward
     * the control flow to another module according to the current module
     * configuration.
     *
     * @access public
     * @param string $action
     */
    public function updateAction($action)
    {
        $_GET[ZNF::ACTION_INDEX] = $action;
    }

    /**
     * Update the name of the module in the request.
     *
     * This method is used by the <i>ZNF_Action_RequestProcessor</i> to forward
     * the control flow to another module according to the current module
     * configuration.
     *
     * @access public
     * @param string $module
     */
    public function updateModule($module)
    {
        $_GET[ZNF::MODULE_INDEX ] = $module;
    }

}

/**
 * <i>ZNFException</i> is the exception type for the <i>ZNF</i> class.
 *
 * <i>ZNFException</i> extends the <i>Exception</i> class of PHP5.
 *
 * @access     public
 * @package    ZNF
 * @author     Alessandro Rossini <http://www.alessandrorossini.org>
 * @author     Graziano Liberati <http://www.liberati.org>
 * @copyright  2004-2007 The ZNF Development Team
 * @license    LGPL License 2.1 <http://www.gnu.org/copyleft/lesser.html>
 * @version    SVN $Id: ZNF.php 44 2007-07-22 23:55:30Z evolic $
 * @since      Release 0.6.1
 * @link       http://www.zeronotice.org
 */
class ZNFException extends Exception
{
}

?>
